import copy
import sys
import concurrent.futures
import multiprocessing
import threading
import time
from math import sqrt
from typing import Iterable, Iterator

print(isinstance([], Iterable))
print(isinstance((), Iterable))
print(isinstance(set(), Iterable))
print(isinstance({}, Iterable))

print(isinstance((), Iterator))

li1 = [1, 2, 3, 4]
it = iter(li1)
print(next(it))
print(next(it))
print(next(it))
print(next(it))
# print(next(it))

class Reverse:
    """Iterator for looping over a sequence backwards."""
    def __init__(self, data):
        self.data = data
        self.index = len(data)

    def __iter__(self):
        return self

    def __next__(self):
        if self.index == 0:
            raise StopIteration
        self.index = self.index - 1
        return self.data[self.index]

rev = Reverse([1, 2, 3, 4])
iter(rev)
for char in rev:
    print(char)


# Generator
generator = (x for x in range(10))
print(generator)
for val in generator:
    print(val)

def fibo():
    a, b = 0, 1
    for _ in range(10):
        yield b
        a, b = b, a + b

f = fibo()
print(next(f))
print(next(f))
print(next(f))
print(next(f))

def fibo2(n):
    a, b = 0, 1
    for _ in range(n):
        yield b
        a, b = b, a + b

fi = fibo2(10)
while True:
    try:
        print(next(fi))
    except StopIteration:
        break

def gen():
    task_id = 0
    int_value = 0
    char_value = "A"
    while True:
        # task_id 为 0 则 int_value +1，task_id 为 1 则 char_value +1
        match task_id:
            case 0:
                task_id = yield int_value  # 返回 int_value，并接收 send() 发送来的值给 task_id
                int_value += 1
            case 1:
                task_id = yield char_value  # 返回 char_value，并接收 send() 发送来的值给 task_id
                char_value = chr(ord(char_value) + 1)
            case _:
                task_id = yield  # 返回 None

g = gen()
print(g.send(None))  # 0
print(g.send(1))  # A
print(g.send(0))  # 1

# 闭包
def outer(a, b):
    def inner(x):
        return a * x + b
    return inner

f1 = outer(2, 3)
print(f1)
print(f1(4))
objects = f1.__closure__
print(objects)
print(objects[0].cell_contents)
print(objects[1].cell_contents)

def decorator(func):
    def wrapper(*args, **kwargs):
        print("Before calling", func.__name__)
        result = func(*args, **kwargs)
        print("After calling", func.__name__)
        return result
    return wrapper

@decorator
def func1(x):
    return x * x

print(func1(3))
decorated_func1 = decorator(func1)
print(decorated_func1(3))


# 将参数转化为整型
def get_integer(f):
    def inner(x):
        x = int(x)
        return f(x)

    return inner

# 将参数转换为非负数
def get_absolute(f):
    def inner(x):
        x = abs(x)
        return f(x)

    return inner

@get_integer
@get_absolute
def func(x):
    """开根号"""
    return sqrt(x)

print(func("-4"))  # 2.0

# 求根号n次
def times(n):
    # 将参数转换为非负数
    def get_absolute(f):
        def inner(x):
            x = abs(x)
            for i in range(n):
                x = f(x)
            return x

        return inner

    return get_absolute

@times(2)
def func(x):
    """开根号"""
    return sqrt(x)

print(func(-16))  # 2.0

class Decorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("Before calling", self.func.__name__)
        result = self.func(*args, **kwargs)
        print("After calling", self.func.__name__)
        return result

@Decorator
def func2(x):
    return x * x

print(func2(4))

# class Worker(multiprocessing.Process):
#     def run(self):
#         print(f"Worker {self.name} is running")
#
# if __name__ == '__main__':
#     for i in range(10):
#         p = Worker()
#         p.run()

# def func():
#     flag = 0
#     while True:
#         print(threading.current_thread().name, f"{flag}" * 5)
#         flag = flag ^ 1  # 替换0和1
#         time.sleep(0.5)
#
# if __name__ == "__main__":
#     t1 = threading.Thread(target=func, name="线程1")
#     t2 = threading.Thread(target=func, name="线程2")
#     t1.start()
#     t2.start()

# class Worker(threading.Thread):
#     def __init__(self, name):
#         super().__init__()
#         self.name = name
#
#     def run(self):
#         flag = 0
#         while True:
#             print(f"\r{self.name}:{str(flag)*5}", end="")
#             flag = flag ^ 1  # 替换0和1
#             time.sleep(0.2)
#
# if __name__ == "__main__":
#     t1 = Worker("线程1")
#     t2 = Worker("线程2")
#     t1.start()
#     t2.start()


def func(name):
    global word
    lock.acquire()
    for i, char in enumerate(word):
        word[i] = chr(ord(char) ^ 1)
    lock.release()
    return word

if __name__ == "__main__":
    word = list("abcdefg")
    lock = threading.Lock()
    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
        futures = [executor.submit(func, f"线程{i}") for i in range(3)]
        for future in concurrent.futures.as_completed(futures):
            print(future.result())

print(sys.path)
print(dir(sys))

li = [1, 2, 3, [4, 5, 6]]
print(li,  id(li), id(li[3]), id(li[3][0]))
li2 = copy.deepcopy(li)
print(li2, id(li2), id(li2[3]),  id(li2[3][0]))